package com.yunwaikeji.gy_tool_library.utils.http.upload;

import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.yunwaikeji.gy_tool_library.utils.GYLogUtils;
import com.yunwaikeji.gy_tool_library.utils.GYUiUtils;
import com.yunwaikeji.gy_tool_library.utils.file.GYFileLoadListener;
import com.yunwaikeji.gy_tool_library.utils.http.GYHttpAsyncTask;
import com.yunwaikeji.gy_tool_library.utils.http.GYHttpListener;
import com.yunwaikeji.gy_tool_library.utils.notification.GYNotificationUtils;

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;

public class GYUploadTask extends GYHttpAsyncTask<GYUploadTask, GYUploadModel<?>> {
    private GYFileLoadListener fileLoadListener;
    private long lastBytes;//前一秒大小
    private long nowBytes;//当前大小
    private long totalBytes;//总计大小
    private long secondBytes;//速度

    public GYUploadTask setFileLoadListener(GYFileLoadListener fileLoadListener) {
        this.fileLoadListener = fileLoadListener;
        return this;
    }

    private final Handler handler = new Handler(Looper.getMainLooper());
    private final Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (nowBytes >= totalBytes) {
                secondBytes = 0;
            } else {
                secondBytes = nowBytes - lastBytes;
                lastBytes = nowBytes;
            }
//            String nowS = GYFileUtils.getFormatSize((double) nowBytes);
//            String totalS = GYFileUtils.getFormatSize((double) totalBytes);
//            String secondBytesS = GYFileUtils.getFormatSize((double) secondBytes);
//            int progress = 0;
//            if (totalBytes > 0) {
//                progress = (int) (nowBytes * 100 / totalBytes);
//            }
//            if (isShowNoticeOnLoading()) {
//                GYNotificationUtils.newNotificationManager()
//                        .setNotificationBuilder(
//                                GYNotificationUtils.getNotificationBuilder()
//                                        .setContentTitle("正在上传")
//                                        .setContentText(nowS + "/" + totalS + "--" + secondBytesS + "/s")
//                                        .setProgress(100, progress, false))
//                        .showOfId(getTagId());
//            }
//            if (nowBytes >= totalBytes) {
//                handler.removeCallbacks(this);
//            } else {
//                handler.postDelayed(this, 1000);
//            }
        }
    };

    public GYUploadTask() {
        setHttpListener(new GYHttpListener<HttpURLConnection>() {
            @Override
            public void start() {
                if (getHttpModel().isShowNoticeOnStart()) {
                    GYNotificationUtils.newNotificationManager()
                            .setNotificationBuilder(
                                    GYNotificationUtils.getNotificationBuilder()
                                            .setContentTitle("上传请求中"))
                            .showOfId(getTagId());
                }
                if (fileLoadListener != null) {
                    fileLoadListener.start();
                }
            }

            @Override
            public void stop() {
                if (fileLoadListener != null) {
                    fileLoadListener.stop();
                }
            }

            @Override
            public void success(HttpURLConnection httpURLConnection) {
                if (fileLoadListener != null) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream(), StandardCharsets.UTF_8);
                                int ch;
                                StringBuilder stringBuilder = new StringBuilder();
                                while ((ch = inputStreamReader.read()) != -1) {
                                    stringBuilder.append((char) ch);
                                }
                                GYUiUtils.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        GYLogUtils.printJson("gylibrary网络框架", "响应\n" + httpURLConnection.getURL().toString(), stringBuilder.toString());
                                        fileLoadListener.success(stringBuilder.toString());
                                        fileLoadListener.finish();
                                    }
                                });
                            } catch (Exception e) {
                                e.printStackTrace();
                                GYUiUtils.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        errorLog(e.toString());
                                    }
                                });
                            }
                        }
                    }).start();
                }
            }

            @Override
            public void error(String error) {
                errorLog(error);
            }

            @Override
            public void finish() {
            }
        });
    }

    @Override
    protected void onPreExecute() {
        handler.post(runnable);
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Object object) {
        handler.removeCallbacks(runnable);
        if (secondBytes != 0) {
            secondBytes = 0;
            GYUiUtils.runOnUiThread(() -> {
                if (fileLoadListener != null) {
                    fileLoadListener.loading(nowBytes, totalBytes, secondBytes);
                }
            });
        }
        super.onPostExecute(object);
    }

    @Override
    public Integer start() {
        if (getHttpModel().getFile() == null) {
            errorLog("文件不能为空");
            return getTagId();
        }
        if (!getHttpModel().getFile().exists()) {
            errorLog("文件不存在");
            return getTagId();
        }
        if (TextUtils.isEmpty(getHttpModel().getFileName())) {
            getHttpModel().setFileName(getHttpModel().getFile().getName());
        }
        totalBytes = getHttpModel().getFile().length();
        setHttpURLConnectionResult(new HttpURLConnectionResult() {
            @Override
            public HttpURLConnection httpURLConnection(HttpURLConnection httpURLConnection) {
                httpURLConnection.setDoOutput(true);//是否容许输出
                httpURLConnection.setDoInput(true);
                httpURLConnection.setUseCaches(false);//是否使用缓存
                httpURLConnection.setAllowUserInteraction(false);
                final String newLine = "\r\n"; // 换行符
                final String boundaryPrefix = "--"; //边界前缀
                // 定义数据分隔线
                final String boundary = String.format("=========%s", System.currentTimeMillis());
                try {
                    // 设置请求头参数RequestProperty
                    httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
                    httpURLConnection.setRequestProperty("Charset", "UTF-8");
                    httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

                    httpURLConnection.setDoInput(true);
                    httpURLConnection.setDoOutput(true);

                    // 构造DataOutputStream流
                    DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream());
                    StringBuilder sb = new StringBuilder();
                    sb.append(boundaryPrefix);
                    sb.append(boundary);
                    sb.append(newLine);
                    // 文件参数
                    sb.append("Content-Disposition: form-data; " + "name=\"").append(getHttpModel().getUrlName()).append("\";filename=\"").append(getHttpModel().getFileName()).append("\"").append(newLine);
                    sb.append("Content-Type:application/octet-stream");
                    // 参数头设置完以后需要两个换行，然后才是参数内容
                    sb.append(newLine);
                    sb.append(newLine);
                    // 将参数头的数据写入到输出流中
                    dos.write(sb.toString().getBytes());

                    // 构造要上传文件的FileInputStream流
                    FileInputStream fis = new FileInputStream(getHttpModel().getFile());
                    // 设置每次写入1024bytes
                    byte[] buffer = new byte[getHttpModel().getCacheSize()];
                    int length;
                    if (getHttpModel().isShowNoticeOnLoading()) {
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                handler.post(runnable);
                            }
                        }).start();
                    }
                    // 从文件读取数据至缓冲区
                    while ((length = fis.read(buffer)) != -1) {
                        // 将资料写入DataOutputStream中
                        dos.write(buffer, 0, length);
                        dos.flush();
                        nowBytes += length;
                        GYUiUtils.runOnUiThread(() -> {
                            if (fileLoadListener != null) {
                                fileLoadListener.loading(nowBytes, totalBytes, secondBytes);
                            }
                        });
                    }
                    dos.writeBytes(newLine);
                    dos.writeBytes(boundaryPrefix + boundary + boundaryPrefix + newLine);
                    // 关闭流
                    fis.close();
                    dos.flush();
                    // 关闭DataOutputStream
                    dos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    errorLog(e.toString());
                }
                return httpURLConnection;
            }
        });
        return super.start();
    }

    private void errorLog(String error) {
        Log.e(getClass().getSimpleName(), error);
        if (fileLoadListener != null) {
            fileLoadListener.error(error);
            fileLoadListener.finish();
        }
    }
}
